<template>
	<view class="public-lazy-load-image" :style="{
			width,
			height,
		}">
		<!-- 加载中 -->
		<image :src="loadSrc" class="current-image current-load" @load="init"  mode="scaleToFill" :style="{
			opacity:isShow?'0':'1',
			borderRadius,
			width,
			height,
			transition: `opacity ${duration/1000}s ${effect}`
			}">
		</image>
		<!-- 加载成功 -->
		<image class="current-image" @load="load" @error="error" v-if="status==1" :src="src" mode="widthFix" :style="{
			opacity:isShow?'1':'0',
			borderRadius,
			width,
			height,
			transition: `opacity ${duration/1000}s ${effect}`
			}">
		</image>
		<!-- 加载失败 -->
		<image class="current-image" v-if="status==2" :src="errorSrc" mode="widthFix" :style="{
			opacity:isShow?'1':'0',
			borderRadius,
			width,
			height,
			transition: `opacity ${duration/1000}s ${effect}`
			}">
		</image>
	</view>
</template>

<script>
	let loadTimer = null
	import loadingImage from '../../static/loading.png'
	import loadFailImage from '../../static/loading.png'
	export default {
		name:"public-lazy-load-image",
		props: {
			//图片圆角 必须带尺寸单位
			borderRadius: {
				type: String,
				default: '0'
			},
			//图片宽度
			width: {
				type: String,
				default: '100%'
			},
			height: {
				type: String,
				default: '100%'
			},
			//图片链接
			src: {
				type: String,
				default: ''
			},
			//当图片加载过快(存在缓存)至少显示多少秒加载动画
			minTimeOut: {
				type: String || Number,
				default: '300'
			},
			//当图片到屏幕哪个位置的时候开始加载 单位px 可以是负数
			showDistance: {
				type: Object,
				default: () => {
					bottom: 20
				}
			},
			//过渡效果  linear / ease / ease-in / ease-out / ease-in-out
			effect: {
				type: String,
				default: 'linear'
			},
			//图片加载成功后的过渡时间 单位毫秒
			duration: {
				type: String || Number,
				default: '300'
			},
			//加载中图片
			loadSrc: {
				type: String,
				default: loadingImage
			},
			//加载失败图片
			errorSrc: {
				type: String,
				default:loadFailImage
			}

		},
		data() {
			return {
				status: 0, //0加载中 1加载成功 2加载失败
				isShow: false
			}
		},
		watch: {
			//当链接变化重新加载
			src() {
				if (!this.isShow) return
				this.status = 0
				this.isShow = false
				this.$nextTick(() => {
					this.status = 1
				})
			}
		},
		destroyed() {
			//页面销毁取消监听
			this.$emit('destroyed')
		},
		methods: {
			load() {
				if (this.minTimeOut == 0) {
					this.isShow = true
				}else{
					let newTimer = new Date().getTime() - loadTimer
					if (newTimer < this.minTimeOut) {
						setTimeout(() => {
							this.isShow = true
						}, this.minTimeOut - newTimer)
					} else {
						this.isShow = true
					}
				}
				
				setTimeout(()=>{
					this.$emit('showSuccess');
				},this.duration)
			},
			error() {
				this.status = 2
				this.isShow = true
			},
			init(){
				let intersectionObserver = uni.createIntersectionObserver(this)
				let load = false
				//当图片加载完的时候取消监听
				this.$once('destroyed', () => {
					intersectionObserver.disconnect()
				})
				intersectionObserver.relativeToViewport(this.showDistance).observe('.current-load', (res) => {
					if (!load && res.intersectionRatio == 0) {
						load = true
						return
					}
					this.$emit('show');
					load = true
					this.status = 1
					loadTimer = new Date().getTime()
					intersectionObserver.disconnect()
				})
			}
		}
	}
</script>

<style lang="scss" scoped>
	.public-lazy-load-image {
		overflow: hidden;
		position: relative;
		.current-image {
			display: block;
			will-change: transform;
		}
		.current-load {
			position: absolute;
			left: 0;
			top: 0;
		}
	}
</style>
